Add support for Model Context Protocol#271
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds support for the Model Context Protocol (MCP) by integrating GLSP MCP servers with Theia AI. The changes enable GLSP diagram editors to expose their functionality through MCP servers that can be discovered and utilized by Theia's AI features.
Key changes:
- New
theia-mcp-integrationpackage that automatically registers GLSP MCP servers with Theia's AI MCP service - Fixed shutdown notification handling to properly notify servers before connection disposal
- Updated workflow example to demonstrate MCP server initialization
Reviewed changes
Copilot reviewed 12 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/theia-mcp-integration/package.json | Defines new package for MCP integration with dependencies on Theia AI and GLSP integration |
| packages/theia-mcp-integration/tsconfig.json | TypeScript configuration for the new MCP integration package |
| packages/theia-mcp-integration/src/browser/theia-mcp-integration-frontend-module.ts | Container module that registers the MCP registration service |
| packages/theia-mcp-integration/src/browser/glsp-mcp-registration.ts | Service that discovers GLSP clients and registers their MCP servers with Theia |
| packages/theia-integration/src/browser/glsp-client-contribution.ts | Fixed to send shutdown notification before disposing connection |
| examples/workflow-theia/src/browser/workflow-glsp-client-contribution.ts | Updated to include MCP server initialization parameters |
| examples/workflow-theia/package.json | Added dependency on new theia-mcp-integration package |
| examples/workflow-theia/tsconfig.json | Added TypeScript project reference to theia-mcp-integration |
| examples/browser-app/package.json | Added Theia AI dependencies to demonstrate MCP integration |
| package.json | Updated workspace pattern to include all packages |
| configs/local-linking.sh | Added server-mcp package to local linking script |
| .vscode/launch.json | Added debug configuration for server-mcp package |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
95ebe92 to
974b6d4
Compare
974b6d4 to
9e1afb7
Compare
Registers GLSP-announced MCP servers with the IDE's MCP frontend service so the agent can use them immediately after IDE startup. MCP integration - Discovers MCP server descriptors on each GLSP client contribution and adds them to the IDE's MCP host on startup. - Triggers an explicit start since the host's autostart hook only fires at frontend init. - Per-registration cleanup releases server entries and state-change subscriptions on GLSP failure or extension dispose, avoiding stale entries across IDE restarts under random-port defaults. Adopters - Set the configuration on the GLSP client contribution to enable MCP for a diagram language. - The workflow example demonstrates the end-to-end wiring with a transient connect notification and a copy-URL action. Misc - Sends a shutdown notification before the GLSP connection drops so the server tears down cleanly with the parent session. Part of eclipse-glsp/glsp#1546
9e1afb7 to
f944f7b
Compare
| env: | ||
| STANDALONE_URL: 'file://${{ github.workspace }}/glsp-client/examples/workflow-standalone/app/diagram.html' | ||
| GLSP_SERVER_PORT: '8081' | ||
| GLSP_MCP_SERVER_PORT: '64577' |
There was a problem hiding this comment.
Why was this added?
Do we currently even have e2e tests for the mcp feature?
There was a problem hiding this comment.
We do not, so I removed it again.
| # Defensive: stale nested @eclipse-glsp copies from prior installs shadow the workspace | ||
| # symlinks via Node's nearest-node_modules-wins resolution → bundle fails. | ||
| # Remove them before re-linking. | ||
| find packages examples -path '*/node_modules/@eclipse-glsp' -type d -exec rm -rf {} + 2>/dev/null || true |
There was a problem hiding this comment.
Not sure if it's worth maintaining this script any longer.
We now have linking functionality built in the glsp cli tool.
We should probably update our repos accordingly.
But that's a thing for a follow-up
There was a problem hiding this comment.
yeah, I think so too, should be done in a proper cleanup.
| return undefined; | ||
| } | ||
|
|
||
| protected async getMcpServerPortFromEnv(): Promise<number | undefined> { |
There was a problem hiding this comment.
We could probably align this into one getPortFromEnv() method that just takes the env var as parameter
Instead of three more or less identical methods
| this.toDispose.push( | ||
| Disposable.create(async () => { | ||
| // Await the shutdown so the wire flushes before we dispose the connection. | ||
| const client = await this.glspClient; |
There was a problem hiding this comment.
If this.glspClient hasn't resolved yet when dispose fires (e.g., contribution disposed during startup), the await will block the async body indefinitely, and connection.dispose() / channel.dispose() will never execute.
The previous code pushed connection and channel as separate disposables, guaranteeing synchronous cleanu
There was a problem hiding this comment.
Good catch! We do a best effort shutdown now if the client already resolved but otherwise we will simply dispose as before.
| "scripts": { | ||
| "build": "tsc -b", | ||
| "clean": "rimraf lib *.tsbuildinfo ", | ||
| "generate:index": "glsp generateIndex src/browser src/common src/node -s -f", |
There was a problem hiding this comment.
| "generate:index": "glsp generateIndex src/browser src/common src/node -s -f", | |
| "generate:index": "glsp generateIndex src/browser -s -f", |
| Generate changelog entries by analyzing merged PRs since the last release. | ||
|
|
||
| Execute these phases in order: | ||
|
|
There was a problem hiding this comment.
The CHANGELOG entry formatting changed from - (dash + 3 spaces) to - (dash + 1 space), which contradicts the style guide in SKILL.md line 84 that specifies "Entry prefix: - (dash + exactly 3 spaces)". If this is an intentional style migration,
the SKILL.md should be updated to match. If not, the CHANGELOG entry should retain the original format.
This might be related to the underlying version of prettier/eslint/markdown-lint that is used. I also experienced similar issues in other glsp projects.
There was a problem hiding this comment.
The prettier actually enforces the 1 space when we do yarn format. I updated the skill for this as it proposes 3 spaces
| * override via `rebind(GlspMcpRegistration).to(YourSubclass)` for environments where | ||
| * servers should be registered but kept off until the user starts them on-demand. | ||
| */ | ||
| protected readonly autostart: boolean = true; |
There was a problem hiding this comment.
Remove the override fluff. (everything after the ;)
| * Aggregated cleanup — owns one inner {@link DisposableCollection} per registration. Dispose | ||
| * triggers `removeServer` for every registration and drops the state-change subscriptions. | ||
| */ | ||
| protected readonly toDispose = new DisposableCollection(); |
There was a problem hiding this comment.
No need to add an additional comment for the general toDispose pattern
| * GLSP servers boot on a random port by default, so a registered URL is stale on the next IDE | ||
| * launch. Drop our registrations on shutdown so the next session starts fresh. | ||
| */ | ||
| dispose(): void { |
There was a problem hiding this comment.
Same. no need to comment dispose
| // Per-registration cleanup group. Disposing it removes the MCP server entry AND drops the | ||
| // state-change subscription. Triggers either on definitive GLSP failure (state listener | ||
| // self-disposes) or on extension dispose (parent collection cascades). | ||
| const perRegistration = new DisposableCollection( |
There was a problem hiding this comment.
maybe remove comment here...
|
@tortmayr Thank you for your feedback. Once the server is merged, I'll do a final update on the PR integrating all your comments. |
What it does
Registers GLSP-announced MCP servers with the IDE's MCP frontend
service so the agent can use them immediately after IDE startup.
MCP integration
and adds them to the IDE's MCP host on startup.
fires at frontend init.
subscriptions on GLSP failure or extension dispose, avoiding
stale entries across IDE restarts under random-port defaults.
Adopters
MCP for a diagram language.
transient connect notification and a copy-URL action.
Misc
so the server tears down cleanly with the parent session.
Part of eclipse-glsp/glsp#1546
Requires eclipse-glsp/glsp-client#456 and eclipse-glsp/glsp-server-node#120
How to test
Follow-ups
Changelog